package com.heima.file.service.impl;

import com.heima.file.config.MinIOConfig;
import com.heima.file.config.MinIOConfigProperties;
import com.heima.file.service.FileStorageService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Import;
import org.springframework.util.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author dongcy
 * @date 2024/11/7 10:59
 * @description v
 */
@Slf4j
@EnableConfigurationProperties(MinIOConfigProperties.class)
@Import(MinIOConfig.class)
@RequiredArgsConstructor
public class MinIOFileStorageService implements FileStorageService {

    private final MinioClient minioClient;

    private final MinIOConfigProperties minIOConfigProperties;

    private final static String separator = "/";


    public String builderFilePath(String dirPath, String fileName) {

        StringBuilder builder = new StringBuilder(50);
        if (!StringUtils.isEmpty(dirPath)) {

            builder.append(dirPath).append(separator);

        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        String todayStr = sdf.format(new Date());
        builder.append(todayStr).append(separator);
        builder.append(fileName);
        return builder.toString();
    }


    /**
     * 上传图片文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return
     */
    @Override
    public String uploadImgFile(String prefix, String filename, InputStream inputStream) {

        String filePath = builderFilePath(prefix, filename);

        try {
            PutObjectArgs po = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/jpg")
                    .bucket(minIOConfigProperties.getBucket())
                    .stream(inputStream, inputStream.available(), -1)
                    .build();


            minioClient.putObject(po);

            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());

            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator + filePath);

            return urlPath.toString();
        } catch (Exception e) {
            log.info("{minio put file error}", e);
            throw new RuntimeException("文件上传失败！");
        }
    }

    /**
     * 上传html文件
     *
     * @param prefix      文件前缀
     * @param filename    文件名
     * @param inputStream 文件流
     * @return
     */
    @Override
    public String uploadHtmlFile(String prefix, String filename, InputStream inputStream) {
        String filePath = builderFilePath(prefix, filename);

        try {
            PutObjectArgs po = PutObjectArgs.builder()
                    .object(filePath)
                    .contentType("image/html")
                    .bucket(minIOConfigProperties.getBucket())
                    .stream(inputStream, inputStream.available(), -1)
                    .build();

            minioClient.putObject(po);

            StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath());

            urlPath.append(separator + minIOConfigProperties.getBucket());
            urlPath.append(separator + filePath);

            return urlPath.toString();
        } catch (Exception e) {
            log.info("{minio put file error}", e);
            throw new RuntimeException("文件上传失败！");
        }
    }

    /**
     * 删除文件
     *
     * @param pathUrl 文件全路径
     */
    @Override
    public void delete(String pathUrl) {

        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");

        int index = key.indexOf(separator);

        String bucket = key.substring(0, index);

        String filePath = key.substring(index + 1);

        RemoveObjectArgs ro = RemoveObjectArgs.builder()
                .bucket(bucket)
                .object(filePath)
                .build();

        try {
            minioClient.removeObject(ro);
        } catch (Exception e) {
            log.error("minio remove file error", pathUrl);
            e.printStackTrace();
            throw new RuntimeException("删除minio文件出错");
        }


    }

    @Override
    public byte[] downLoadFile(String pathUrl) {
        String key = pathUrl.replace(minIOConfigProperties.getEndpoint() + "/", "");

        int index = key.indexOf(separator);

        String bucket = key.substring(0, index);

        String filePath = key.substring(index + 1);


        InputStream is = null;

        try {
            minioClient.getObject(GetObjectArgs.builder()
                    .bucket(minIOConfigProperties.getBucket())
                    .object(filePath)
                    .build());
        } catch (Exception e) {
            log.error("minio download file error:{}", pathUrl);
            e.printStackTrace();
            throw new RuntimeException("文件下载出错");
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int len = 0;
        while (true) {
            try {
                if (!((len = is.read(buff, 0, 100)) > 0)) {
                    break;
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            baos.write(buff, 0, len);
        }


        return baos.toByteArray();
    }
}
